
#include "queue.h"
#include "main.h"

Queue::Queue() {
	this->max_num = 10;
	this->front = 1;
	this->rear = 0;
	this->list = (msg_t *) malloc(sizeof(msg_t) * max_num + 1);
	pthread_mutex_init(&(this->lock), NULL);
	sem_init(&(this->sem), 0, 0);
}

Queue::Queue(int max_num) {
	this->max_num = max_num;
	this->front = 1;
	this->rear = 0;
	this->list = (msg_t *) malloc(sizeof(msg_t) * max_num + 1);
	pthread_mutex_init(&(this->lock), NULL);
}

Queue::~Queue() {
	free(this->list);
	pthread_mutex_destroy(&(this->lock));
	sem_destroy(&(this->sem));
}

msg_t Queue::pop() {
	int index;
	msg_t msg = NULL;

	sem_wait(&(this->sem));
	pthread_mutex_lock(&(this->lock));
	if (((this->rear + 1) % this->max_num) != this->front) {
		index = this->front;
		this->front = (this->front + 1) % this->max_num;
		msg = list[index];
	}
	pthread_mutex_unlock(&(this->lock));

	return msg;
}

int Queue::push(msg_t a) {
	int index;

	pthread_mutex_lock(&(this->lock));
	if (((this->rear + 2) % this->max_num) != this->front) {
		index = (this->rear + 1) % this->max_num;
		this->rear = index;
		list[index] = a;
		pthread_mutex_unlock(&(this->lock));
		sem_post(&(this->sem));
	} else {
		pthread_mutex_unlock(&(this->lock));
		return -1;
	}

	return 0;
}

msg_t Queue::msg_create(int data_size, int extra_size) {
	msg_t msg;

	msg = (msg_t) malloc(sizeof(struct msg) + data_size + extra_size);
	if(msg != NULL){
		msg->result = MSG_RESULT_DEFAULT;
		msg->self = msg;
		msg->data = (void *) (((unsigned int) &(msg->extra_data)) + sizeof(void *));
		msg->extra_data = (void *) ((unsigned int) msg->data + data_size);
	}
	return msg;
}

void Queue::msg_destroy(msg_t msg) {
	if(msg != NULL)
		free(msg->self);
}

int Queue::get_max_num() {
	return this->max_num;
}

